package greensimulation;

import java.awt.Dimension;
import java.awt.Toolkit;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextBox;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.animation.Timeline;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
import javafx.util.Duration;

public class RegionAll extends Region {
    private static final Duration DURATION500 = Duration.valueOf(500);
    private static final Duration DURATION1000 = Duration.valueOf(1000);
    private static final Interpolator INTERPOLATOR = Interpolator.EASE_BOTH;
    private Scene scene;
    private Stage stage;
    private Group group_generateGrid = new Group();
    private Group group_computers = new Group();
    private Group group_awayComputers = new Group();
    private Group group_greenRatio = new Group();
    private TextBox textInput_generateGrid = new TextBox(5);
    private Button button_generateGrid = new Button("Generate the grid");
    private boolean isGridGenerated = false;
    private Integer numberOfPC;
    private Timeline timeline;
    private TextBox textInput_greenRatio = new TextBox(4);
    private Button button_greenRatio = new Button("Update green ratio");
    private Grid grid;
    private Button button_arrow;
    private Rectangle rectangle_separator;
    private Group group_jobs = new Group();
    private Button button_addJob;
    private Button button_addRandomJobs;
    private Button button_scheduleJob;
    private ListView list_jobs;
    private Group tmpJobs = new Group();
    private TextBox text_randomJobs;
    private TextBox text_jobTime;
    private TextBox text_jobGreen;
    
    public RegionAll(Scene scene, Stage stage){
        this.scene = scene;
        this.stage = stage;
        this.scene.setFill(Color.WHITE);
        getChildren().addAll(group_generateGrid, group_computers, group_awayComputers, group_greenRatio, group_jobs, tmpJobs);
        button_generateGrid.setTranslateX(45f);
        button_generateGrid.setOnAction(new EventHandler(){
            public void handle(Event e){
                generateGrid();
            }
        });
        textInput_generateGrid.setText("20");
        textInput_generateGrid.setOnKeyPressed(new EventHandler<KeyEvent>() {
            public void handle(KeyEvent ke) {
                if (ke.getCode() == KeyCode.ENTER)
                    generateGrid();
            }
        });
        group_generateGrid.getChildren().addAll(textInput_generateGrid, button_generateGrid);
    }
    
    private void generateGrid(){
        if(!isGridGenerated){
            numberOfPC = Integer.parseInt(textInput_generateGrid.getRawText());
            if(numberOfPC != null){
                isGridGenerated = true;
                
                grid = new Grid(numberOfPC, stage);
                grid.setTranslateY(20);
                group_computers.getChildren().add(grid);
                
                timeline = new Timeline();
                final ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
                
                Toolkit toolkit = Toolkit.getDefaultToolkit();
                Dimension scrnsize = toolkit.getScreenSize();
                
               double finalStageWidth = grid.getGridWidth();
               double finalStageHeight = grid.getGridHeight()+60;
               double finalStageX = (scrnsize.width-finalStageWidth)/2;
               double finalStageY = (scrnsize.height-finalStageHeight)/2;
                
                keyFrames.addAll(
                        new KeyFrame(DURATION500, new KeyValue(textInput_generateGrid.opacityProperty(), 0, INTERPOLATOR)),
                        new KeyFrame(DURATION500, new KeyValue(button_generateGrid.opacityProperty(), 0, INTERPOLATOR)),
                        new KeyFrame(DURATION500, new KeyValue(stage.widthProperty(), finalStageWidth)),
                        new KeyFrame(DURATION500, new KeyValue(stage.heightProperty(), finalStageHeight)),
                        new KeyFrame(DURATION500, new KeyValue(stage.xProperty(), finalStageX, INTERPOLATOR)),
                        new KeyFrame(DURATION500, new KeyValue(stage.yProperty(), finalStageY, INTERPOLATOR))
                        );
                
                timeline.play();
                
                initGreenRatioGUI();
            }
        }
    }
    
    private void initGreenRatioGUI(){
        button_greenRatio.setTranslateX(40f);
        button_greenRatio.setOnAction(new EventHandler(){
            public void handle(Event e){
                updateGreenRatio();
            }
        });
        textInput_greenRatio.setText("0.75");
        textInput_greenRatio.setOnKeyPressed(new EventHandler<KeyEvent>() {
            public void handle(KeyEvent ke) {
                if (ke.getCode() == KeyCode.ENTER)
                    updateGreenRatio();
            }
        });
        group_greenRatio.getChildren().addAll(textInput_greenRatio, button_greenRatio);
        group_greenRatio.setTranslateX(20);
        group_greenRatio.setTranslateY(10);
        
        button_arrow = new Button("  ->  ");
        button_arrow.setTranslateX(grid.getGridWidth()-105);
        button_arrow.setOnAction(new EventHandler<ActionEvent>() {
            public void handle(ActionEvent event) {
                clickOnTheArrow();
            }
        });
        rectangle_separator = new Rectangle(grid.getGridWidth()-grid.X_OFFSET-8, -50, 3d, 2000);
        group_greenRatio.getChildren().addAll(rectangle_separator, button_arrow);
        
        textInput_greenRatio.requestFocus();
    }
    
    private void updateGreenRatio(){
        Double greenRatio = Double.parseDouble(textInput_greenRatio.getRawText());
        if(greenRatio != null){
            grid.updateGreenRatio(greenRatio);
        }
    }
    
    private void clickOnTheArrow(){
        double addedWidth = 250;
        double gridWidth = grid.getGridWidth();
        double height = stage.getHeight();
        
        group_jobs.setTranslateX(gridWidth+15);
        group_jobs.setTranslateY(10);
        
        button_addJob = new Button("Add job");
        button_addJob.setPrefWidth(addedWidth/2-25);
        button_addRandomJobs = new Button("Add random jobs");
        button_addRandomJobs.setTranslateX(addedWidth/2-20);
        button_addRandomJobs.setPrefWidth(addedWidth/2-25);
        button_scheduleJob = new Button("Schedule one");
        button_scheduleJob.setTranslateY(25);
        button_scheduleJob.setPrefWidth(addedWidth-45);
        list_jobs = new ListView();
        list_jobs.setTranslateY(60);
        list_jobs.setPrefHeight(height-120);
        list_jobs.setPrefWidth(addedWidth-45);
        
        button_addJob.setOnAction(new EventHandler(){
            public void handle(Event e){
                clickOnAddJob();
            }
        });
        button_addRandomJobs.setOnAction(new EventHandler(){
            public void handle(Event e){
                clickOnAddRandomJobs();
            }
        });
        button_scheduleJob.setOnAction(new EventHandler(){
            public void handle(Event e){
                clickOnSchedule();
            }
        });        
        
        group_jobs.setOpacity(0);
        group_jobs.getChildren().addAll(button_addJob, button_addRandomJobs, button_scheduleJob, list_jobs);
        
        timeline = new Timeline();
        final ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
        
        keyFrames.addAll(
                new KeyFrame(DURATION500, new KeyValue(stage.widthProperty(), gridWidth+addedWidth, INTERPOLATOR)),
                new KeyFrame(DURATION500, new KeyValue(button_arrow.opacityProperty(), 0, INTERPOLATOR)),
                new KeyFrame(DURATION500, new KeyValue(group_jobs.opacityProperty(), 1, INTERPOLATOR))
                );
        
        keyFrames.addAll(new KeyFrame(DURATION500, new EventHandler<ActionEvent>() {
            public void handle(ActionEvent event) {
                group_greenRatio.getChildren().clear();
                group_greenRatio.getChildren().addAll(textInput_greenRatio, button_greenRatio, rectangle_separator);
            }
        }));
        
        timeline.play();
    }
    
    private void clickOnAddJob(){
        Timeline tl = extendJobPart(115, true);
        final ObservableList<KeyFrame> keyFrames = tl.getKeyFrames();
        
        Group total = new Group();
        total.setTranslateX(grid.getGridWidth()+20);
        total.setTranslateY(45);
        
        Group g1 = new Group();
        g1.setTranslateY(5);
        
        Label label = new Label("Time :");
        label.setPrefWidth(97);
        label.setAlignment(Pos.CENTER);
        label.setFont(new Font(Font.getDefault().getFamily(), 16));

        text_jobTime = new TextBox();
        text_jobTime.setPrefWidth(80);
        text_jobTime.setTranslateX(97);
        
        g1.getChildren().addAll(label, text_jobTime);
        
        
        Group g2 = new Group();
        g2.setTranslateY(30);
        
        Label label2 = new Label("Cursor :");
        label2.setPrefWidth(97);
        label2.setAlignment(Pos.CENTER);
        label2.setFont(new Font(Font.getDefault().getFamily(), 16));

        text_jobGreen = new TextBox(10);
        text_jobGreen.setPrefWidth(80);
        text_jobGreen.setTranslateX(97);
        
        g2.getChildren().addAll(label2, text_jobGreen);

        
        Group g3 = new Group();
        g3.setTranslateY(60);
        g3.setTranslateX(20);
        
        Button b = new Button("OK");
        b.setPrefWidth(75);
        Button b2 = new Button("Cancel");
        b2.setPrefWidth(75);
        b2.setTranslateX(80);
        
        g3.getChildren().addAll(b, b2);
        
        text_jobGreen.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                if(event.getCode() == KeyCode.ENTER)
                   addOneJob(text_jobTime.getRawText(), text_jobGreen.getRawText());            }
        });
        b.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                addOneJob(text_jobTime.getRawText(), text_jobGreen.getRawText());
            }
        });
        b2.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                addOneJob("", "");
            }
        });
        
        total.getChildren().addAll(g1, g2, g3);
        total.setOpacity(0);
        tmpJobs.getChildren().addAll(total);
        
        keyFrames.addAll(
                new KeyFrame(DURATION500, new KeyValue(total.opacityProperty(), 1, INTERPOLATOR))
                );
        
        tl.play();
        
        text_jobTime.requestFocus();
    }
    
    private void addOneJob(String Time, String Green){
        if( !Time.isEmpty() && !Green.isEmpty() ){
            Integer time = Integer.parseInt(Time);
            Integer green = Integer.parseInt(Green);
            if( time != null && green != null ){
                System.out.println(time + " | " + green);
            }
        }
        
        extendJobPart(-115, false).play();
    }
    
    private void clickOnAddRandomJobs(){
        Timeline tl = extendJobPart(80, true);
        final ObservableList<KeyFrame> keyFrames = tl.getKeyFrames();
        
        Group total = new Group();
        total.setTranslateX(grid.getGridWidth()+20);
        total.setTranslateY(45);
        Label label = new Label("How many random jobs ?");
        label.setPrefWidth(195);
        label.setAlignment(Pos.CENTER);
        label.setFont(new Font(Font.getDefault().getFamily(), 16));
        
        Group g2 = new Group();
        g2.setTranslateY(25);
        g2.setTranslateX(13);
        text_randomJobs = new TextBox(10);
        Button b = new Button("OK");
        b.setTranslateX(79);
        Button b2 = new Button("Cancel");
        b2.setTranslateX(115);
        
        text_randomJobs.setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                if(event.getCode() == KeyCode.ENTER)
                    generateRandomJobs(text_randomJobs.getRawText());
            }
        });
        b.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                generateRandomJobs(text_randomJobs.getRawText());
            }
        });
        b2.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                generateRandomJobs("0");
            }
        });
        
        g2.getChildren().addAll(text_randomJobs, b, b2);
        total.getChildren().addAll(label, g2);
        total.setOpacity(0);
        tmpJobs.getChildren().addAll(total);
        
        keyFrames.addAll(
                new KeyFrame(DURATION500, new KeyValue(total.opacityProperty(), 1, INTERPOLATOR))
                );
        
        tl.play();
        
        text_randomJobs.requestFocus();
    }
    
    private void generateRandomJobs(String N){
        if( !N.isEmpty() ){
            Integer n = Integer.parseInt(N);
            if( n != null){
                System.out.println(n);
            }
        }
        
        extendJobPart(-80, false).play();
    }
    
    private Timeline extendJobPart(double offset, boolean createBlackPart){
        Timeline tl = new Timeline();
        final ObservableList<KeyFrame> keyFrames = tl.getKeyFrames();
        
        keyFrames.addAll(
                new KeyFrame(DURATION500, new KeyValue(button_scheduleJob.translateYProperty(), button_scheduleJob.getTranslateY()+offset, INTERPOLATOR)),
                new KeyFrame(DURATION500, new KeyValue(list_jobs.translateYProperty(), list_jobs.getTranslateY()+offset, INTERPOLATOR)),
                new KeyFrame(DURATION500, new KeyValue(list_jobs.prefHeightProperty(), list_jobs.getPrefHeight()-offset, INTERPOLATOR))
                );

        if(createBlackPart){
            Rectangle r = new Rectangle(stage.getWidth(), stage.getHeight(), Color.BLACK);
            r.setOpacity(0);
            Rectangle r2 = new Rectangle(grid.getGridWidth() + 15, 35, 205, 0);
            r2.setArcHeight(20);
            r2.setArcWidth(20);
            r2.setFill(Color.WHITE);
            r2.setOnMouseClicked(new EventHandler<MouseEvent>() {
                public void handle(MouseEvent e){
                    extendJobPart(-90, false);
                }
            });
            tmpJobs.getChildren().addAll(r, r2);
            tmpJobs.setOpacity(1);

            keyFrames.addAll(
                    new KeyFrame(DURATION500, new KeyValue(r.opacityProperty(), 0.7, INTERPOLATOR)),
                    new KeyFrame(DURATION500, new KeyValue(r2.heightProperty(), offset - 8, INTERPOLATOR)));
        }
        else {
            keyFrames.addAll(
                new KeyFrame(DURATION500, new KeyValue(tmpJobs.opacityProperty(), 0, INTERPOLATOR)));
            keyFrames.add(new KeyFrame(DURATION500, new EventHandler() {
                        public void handle(Event e) {
                                    tmpJobs.getChildren().clear();
                        }
                    }));
        }

        return tl;
    }
    
    private void clickOnSchedule(){
        
    }
}
